/*
    Matali Physics Demo
    Copyright (c) 2011 KOMIRES Sp. z o. o.
 */
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using Komires.MataliPhysics;

namespace MataliPhysicsDemo
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class DemoFont3D
    {
        Demo demo;
        Texture2D texture;
        float[] fontTranslations = new float[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 6, 11, 8, 13, 10, 4, 6, 6, 8, 11, 5, 6, 5, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 6, 6, 11, 11, 11, 7, 13, 9, 9, 9, 10, 8, 8, 10, 10, 6, 6, 9, 8, 11, 10, 10, 8, 10, 9, 8, 9, 10, 9, 13, 9, 9, 8, 6, 6, 6, 11, 8, 8, 8, 8, 7, 8, 8, 5, 8, 8, 4, 5, 8, 4, 12, 8, 8, 8, 8, 6, 7, 5, 8, 8, 11, 7, 8, 7, 7, 6, 7, 11, 13, 13, 13, 13, 13, 4, 1, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 4, 5, 8, 8, 8, 8, 6, 8, 8, 13, 7, 9, 11, 6, 13, 8, 7, 11, 7, 7, 8, 8, 8, 6, 8, 7, 7, 9, 13, 13, 13, 7, 9, 9, 9, 9, 9, 9, 13, 9, 8, 8, 8, 8, 6, 6, 6, 6, 10, 10, 10, 10, 10, 10, 10, 11, 10, 10, 10, 10, 10, 9, 8, 8, 8, 8, 8, 8, 8, 8, 13, 7, 8, 8, 8, 8, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 11, 8, 8, 8, 8, 8, 8, 8, 8 };
        VertexPositionColorTexture[] fontVertices = new VertexPositionColorTexture[4];
        BasicEffect effect;

        BlendState fontBlendState;

        public BasicEffect Effect { get { return effect; } }

        public DemoFont3D(GraphicsDevice device, Demo demo, string fontTextureName)
        {
            this.demo = demo;

            texture = demo.Textures[fontTextureName];

            effect = new BasicEffect(device);

            fontBlendState = new BlendState();
            fontBlendState.AlphaSourceBlend = Blend.One;
            fontBlendState.AlphaDestinationBlend = Blend.One;
            fontBlendState.AlphaBlendFunction = BlendFunction.Add;
            fontBlendState.ColorSourceBlend = Blend.One;
            fontBlendState.ColorDestinationBlend = Blend.One;
            fontBlendState.ColorBlendFunction = BlendFunction.Add;
        }

        public void Begin()
        {
            demo.GraphicsDevice.DepthStencilState = DepthStencilState.DepthRead;
            demo.GraphicsDevice.BlendState = fontBlendState;
            demo.GraphicsDevice.RasterizerState = RasterizerState.CullClockwise;
            effect.LightingEnabled = false;
            effect.TextureEnabled = true;
            effect.Texture = texture;
            effect.VertexColorEnabled = true;
        }

        public void End()
        {
            demo.GraphicsDevice.DepthStencilState = DepthStencilState.Default;
            demo.GraphicsDevice.BlendState = BlendState.Opaque;
        }

        public void Draw(float x, float y, float z, float scaleX, float scaleY, string text, Color color)
        {
            Matrix initFontWorld, fontWorld, fontTranslation, world;

            initFontWorld = fontWorld = effect.World;

            Matrix.CreateTranslation(x, y, 0.0f, out fontTranslation);
            Matrix.Multiply(ref fontWorld, ref fontTranslation, out world);
            effect.World = world;

            int fontValue;
            float u, v, translation;
            float fontSizeX = 16 * scaleX;
            float fontSizeY = 16 * scaleY;
            float fontWidth = 1.0f / 16.0f;
            float fontHeight = 1.0f / 16.0f;
            float fontMargin = 1.0f / 256.0f;

            for (int i = 0; i < text.Length; i++)
            {
                fontValue = (int)text[i];
                u = (float)(fontValue % 16) * fontWidth + fontMargin;
                v = (float)(fontValue >> 4) * fontHeight + fontMargin;
                translation = fontTranslations[fontValue];

                fontVertices[0].Position.X = 0.0f;
                fontVertices[0].Position.Y = 0.0f;
                fontVertices[0].Position.Z = z;
                fontVertices[0].TextureCoordinate.X = u;
                fontVertices[0].TextureCoordinate.Y = v + fontHeight;
                fontVertices[0].Color = color;

                fontVertices[1].Position.X = fontSizeX;
                fontVertices[1].Position.Y = 0.0f;
                fontVertices[1].Position.Z = z;
                fontVertices[1].TextureCoordinate.X = u + fontWidth;
                fontVertices[1].TextureCoordinate.Y = v + fontHeight;
                fontVertices[1].Color = color;

                fontVertices[2].Position.X = 0.0f;
                fontVertices[2].Position.Y = fontSizeY;
                fontVertices[2].Position.Z = z;
                fontVertices[2].TextureCoordinate.X = u;
                fontVertices[2].TextureCoordinate.Y = v;
                fontVertices[2].Color = color;

                fontVertices[3].Position.X = fontSizeX;
                fontVertices[3].Position.Y = fontSizeY;
                fontVertices[3].Position.Z = z;
                fontVertices[3].TextureCoordinate.X = u + fontWidth;
                fontVertices[3].TextureCoordinate.Y = v;
                fontVertices[3].Color = color;

                Effect.Techniques[0].Passes[0].Apply();

                demo.GraphicsDevice.DrawUserPrimitives<VertexPositionColorTexture>(PrimitiveType.TriangleStrip, fontVertices, 0, 2);

                fontWorld = effect.World;

                Matrix.CreateTranslation(translation * scaleX, 0.0f, 0.0f, out fontTranslation);
                Matrix.Multiply(ref fontWorld, ref fontTranslation, out world);
                effect.World = world;
            }

            effect.World = initFontWorld;
        }
    }
}
